package org.web.locks.databasedistributedlocks.sdk.biz;

import org.web.locks.databasedistributedlocks.sdk.dto.LockConstants;
import org.web.locks.databasedistributedlocks.sdk.dto.LockDTO;
import org.web.locks.databasedistributedlocks.sdk.dto.TryLockDTO;
import org.web.locks.databasedistributedlocks.sdk.helper.ProcessIdentifierHelper;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

public interface Locks extends LockConstants {

    /**
     * 尝试获取锁，如果获取成功，则返回 true，否则返回 false。
     *
     * @param lockMarker     锁标记，不能为空，字符长度不能超过{@value #MAX_LOCK_MARKER_LENGTH}个字符。由调用方提供。
     * @param lockExpireTime 锁的超时时间，单位：毫秒。不设置，则使用默认值，默认值为 {@value #DEFAULT_EXPIRE_TIME } 毫秒。最小值为 500 毫秒，最大值不能超过 {@value #MAX_LOCK_EXPIRE_TIME} 毫秒，即 5 分钟。
     * @param lockOwner      锁的拥有者标识，如果为空，则使用UUID作为锁的拥有者标识。
     * @param tryTimeout     获取锁的超时时间，单位：毫秒。最大值不能超过 {@value #MAX_TRY_LOCK_TIMEOUT} 毫秒，最小值为 {@value #MIN_TRY_TIMEOUT} 毫秒，即不等待。
     * @param tryCount       尝试次数，默认值为 {@value #DEFAULT_TRY_COUNT}，最小值为 {@value #DEFAULT_TRY_COUNT}，即最少尝试{@value #DEFAULT_TRY_COUNT}次，最大值为 {@value #MAX_TRY_COUNT}。
     * @return 返回 {@link TryLockDTO} 对象，包含是否成功获取锁、锁的拥有者标识、锁的超时时间等信息。
     */
    default TryLockDTO tryLockDTO(
          @NotEmpty(message = "锁标记不能为空")
          @Size(max = MAX_LOCK_MARKER_LENGTH, message = "锁标记不能超过{" + MAX_LOCK_MARKER_LENGTH + "}个字符")
          String lockMarker,
          @Max(value = MAX_LOCK_EXPIRE_TIME, message = "设置锁定的最长时间不能超过{" + MAX_LOCK_EXPIRE_TIME + "}毫秒，即5分钟")
          @Min(value = MIN_LOCK_EXPIRE_TIME, message = "设置锁定的时间不能小于{" + MIN_LOCK_EXPIRE_TIME + "}毫秒")
          Integer lockExpireTime,
          @Size(max = MAX_LOCK_OWNER_LENGTH, message = "锁拥有者标识，不能超过{" + MAX_LOCK_OWNER_LENGTH + "}个字符")
          String lockOwner,
          @Max(value = MAX_TRY_LOCK_TIMEOUT, message = "设置获取锁的超时时间不能超过{" + MAX_TRY_LOCK_TIMEOUT + "}毫秒，即5分钟")
          @Min(value = MIN_TRY_TIMEOUT, message = "设置获取锁的超时时间不能小于{" + MIN_TRY_TIMEOUT + "}毫秒")
          Long tryTimeout,
          @Max(value = MAX_TRY_COUNT, message = "尝试次数不能超过" + MAX_TRY_COUNT)
          @Min(value = DEFAULT_TRY_COUNT, message = "尝试次数不能小于" + DEFAULT_TRY_COUNT)
          Integer tryCount) {
        return tryLockDTO(new TryLockDTO(lockMarker, lockExpireTime, lockOwner, tryTimeout, tryCount));
    }


    default TryLockDTO tryLockDTO(@NotEmpty(message = "锁标记不能为空")
                                  @Size(max = MAX_LOCK_MARKER_LENGTH, message = "锁标记不能超过{" + MAX_LOCK_MARKER_LENGTH + "}个字符")
                                  String lockMarker){
        return tryLockDTO(new TryLockDTO(lockMarker, null, null, null, null));
    }


    default TryLockDTO tryLockDTO(TryLockDTO tryLockDTO) {
        throw new UnsupportedOperationException("请实现此方法，处理锁获取的业务逻辑");
    }

    default boolean releaseLock(@NotEmpty(message = "锁标记不能为空")
                                @Size(max = MAX_LOCK_MARKER_LENGTH, message = "锁标记不能超过{" + MAX_LOCK_MARKER_LENGTH + "}个字符")
                                String lockMarker) {
        return releaseLock(new LockDTO(lockMarker, null, null));
    }

    default boolean releaseLock(@NotEmpty(message = "锁标记不能为空")
                                @Size(max = MAX_LOCK_MARKER_LENGTH, message = "锁标记不能超过{" + MAX_LOCK_MARKER_LENGTH + "}个字符")
                                String lockMarker,
                                @Size(max = MAX_LOCK_OWNER_LENGTH, message = "锁拥有者标识，不能超过{" + MAX_LOCK_OWNER_LENGTH + "}个字符")
                                String lockOwner) {
        return releaseLock(new LockDTO(lockMarker, null, lockOwner));
    }

    default boolean releaseLock(LockDTO lockDTO) {
        throw new UnsupportedOperationException("请实现此方法，处理锁释放的业务逻辑");
    }



    /**
     * 默认实现，获取当前进程的唯一标识：由进程ID和主机名组成
     *
     * @param networkInterfaceName 网卡名称，用于获取进程标识符。
     */
    default String getLockOwnerFirstPart(String networkInterfaceName) {
        return ProcessIdentifierHelper.getProcessIdentifier();
    }

}
